from django.contrib.auth.hashers import make_password, check_password
from django.db.models import Q
from rest_framework.decorators import api_view
from rest_framework.pagination import PageNumberPagination
from rest_framework_simplejwt.exceptions import TokenError
from rest_framework_simplejwt.tokens import RefreshToken

from apps.cbsp.models import Cbsp_Bi_Records
from apps.common.send_sms_4a import send_sms_code
from apps.pbi.models import Client, BusinessOpportunity
from apps.system.filters import TodolistsFilter, DictFilter, OperationRecordFilter, LoginLogFilter
from apps.system.md5 import decode
from apps.system.models import Company, Region, ToDoList, OperationRecord
from apps.system.schemas import SMSGetTokenRequest, SMSRequest
from apps.system.serializers import CompaniesSerializer, RegionsSerializer, TodolistsSerializer, ClientsSerializer, \
    BusinessOpportunitySerializer, BusinessOpportunity_orderSerializer, Cbsp_Bi_RecordsSerializer, \
    OperationRecordSerializer, LoginLogSerializer
from configs.sms_4A import SEND_SMS_METHOD, APP_ID, AUTH_SMS_METHOD, APP_ID_Evaluation
from extensions.common.base import *
from extensions.common.schema import *
from extensions.common.schema import *
from extensions.common.base import *
from extensions.permissions import *
from extensions.exceptions import *
from extensions.viewsets import *
from apps.system.serializers import *
from apps.system.schemas import *
from apps.system.models import *
from apps.common.com import Pagination
from rest_framework import status, filters


class PaginationCls(PageNumberPagination):
    page_size = 15
    page_size_query_param = 'page_size'
    page_query_param = 'page'
    max_page_size = 100000

#选项分页
class OptionPaginationCls(PageNumberPagination):
    page_size = 99999
    page_size_query_param = 'page_size'
    page_query_param = 'page'
    max_page_size = 100000

class PermissionGroupViewSet(BaseViewSet, ListModelMixin):
    """权限分组"""

    serializer_class = PermissionGroupSerializer
    permission_classes = [IsAuthenticated]
    pagination_class = None
    ordering = ['id']
    queryset = PermissionGroup.objects.all()

    def get_queryset(self):
        return self.queryset.prefetch_related('permissions').all()

class SystemConfigViewSet(BaseViewSet, ListModelMixin):
    """权限分组"""

    serializer_class = PermissionGroupSerializer
    permission_classes = [IsAuthenticated]
    pagination_class = None
    ordering = ['id']
    queryset = PermissionGroup.objects.all()

    def get_queryset(self):
        return self.queryset.prefetch_related('permissions').all()




class RoleViewSet(ModelViewSet):
    """角色"""

    serializer_class = RoleSerializer
    permission_classes = [IsAuthenticated, IsManagerPermission]
    pagination_class = Pagination
    search_fields = ['name']
    queryset = Role.objects.all()

    @transaction.atomic
    def perform_update(self, serializer):
        role = serializer.save()

        # 同步用户权限
        users = role.users.prefetch_related('roles', 'roles__permissions').all()
        for user in users:
            permissions = {permission.code for role in user.roles.all()
                           for permission in role.permissions.all()}
            user.permissions = list(permissions)
        else:
            User.objects.bulk_update(users, ['permissions'])

    @transaction.atomic
    def perform_destroy(self, instance):
        users = instance.users.all()
        instance.delete()

        # 同步用户权限
        for user in users.prefetch_related('roles', 'roles__permissions').all():
            permissions = {permission.code for role in user.roles.all()
                           for permission in role.permissions.all()}
            user.permissions = list(permissions)
        else:
            User.objects.bulk_update(users, ['permissions'])


class CompaniesViewSet(ModelViewSet):
    """公司"""
    serializer_class = CompaniesSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    # permission_classes = [IsAuthenticated]
    pagination_class = PaginationCls
    search_fields = ['name']
    ordering_fields = ['id','name','index']
    queryset = Company.objects.all()


class ClientsViewSet(ModelViewSet):
    """客户"""
    serializer_class = ClientsSerializer
    search_fields = ['name']
    ordering_fields = ['id','name']
    queryset = Client.objects.all()

    def get_queryset(self):
        base_query = Q(del_flag=False)
        # 根据权限添加额外的查询条件
        if "pbi_view_qs" not in self.request.user.permissions:
            base_query &= Q(company=self.request.user.company)

        queryset = Client.objects.filter(base_query)

        return queryset


class BusinessOpportunityViewSet(ModelViewSet):
    """商机"""
    serializer_class = BusinessOpportunitySerializer
    search_fields = ['name']
    ordering_fields = ['id','name']

    def get_queryset(self):
        base_query = Q(del_flag=False)
        # 根据权限添加额外的查询条件
        if "pbi_view_qs" not in self.request.user.permissions:
            base_query &= Q(company=self.request.user.company)
        #如果在Contract中有关联的商机，那么就不显示
        # base_query &= Q(Contract_business_opportunity__isnull=True)

        queryset = BusinessOpportunity.objects.filter(base_query)

        return queryset


class BusinessOpportunity_orderViewSet(ModelViewSet):
    """商机为订单选项"""
    serializer_class = BusinessOpportunity_orderSerializer
    search_fields = ['name']
    ordering_fields = ['id','name']

    def get_queryset(self):
        base_query = Q(del_flag=False) & Q(is_frame=True)
        # 根据权限添加额外的查询条件
        if "pbi_view_qs" not in self.request.user.permissions:
            #如果BusinessOpportunity的company.name=='省分公司'，那么就显示所有的商机
            base_query &= (Q(company=self.request.user.company) | Q(company__name='省分公司'))
        #如果在Contract中有关联的商机，那么就显示
        base_query &= Q(Contract_business_opportunity__isnull=False)

        queryset = BusinessOpportunity.objects.filter(base_query)

        return queryset

class Cbsp_Bi_RecordsViewSet(ModelViewSet):
    """CBSP基本信息"""
    serializer_class = Cbsp_Bi_RecordsSerializer
    search_fields = ['name']
    ordering_fields = ['id','name']

    def get_queryset(self):
        base_query = Q(del_flag=False)
        # 根据权限添加额外的查询条件
        if "cbsp_view_all" not in self.request.user.permissions:
            base_query &= (Q(company=self.request.user.company))

        queryset = Cbsp_Bi_Records.objects.filter(base_query)

        return queryset


class TodolistsViewSet(ModelViewSet):
    """公司"""
    serializer_class = TodolistsSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    permission_classes = [IsAuthenticated]
    pagination_class = PaginationCls
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    filter_class = TodolistsFilter
    search_fields = ['name']
    ordering_fields = ['id','deadline','create_time','finish_time']
    queryset = ToDoList.objects.filter(del_flag=False)


class OperationRecordsPagination(PageNumberPagination):
    page_size = 15
    page_size_query_param = 'page_size'
    page_query_param = 'current'
    max_page_size = 100000



class OperationRecordsViewSet(ModelViewSet):
    """操作日志"""
    serializer_class = OperationRecordSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    permission_classes = [IsAuthenticated]
    pagination_class = OperationRecordsPagination
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    filter_class = OperationRecordFilter
    search_fields = ['user__name','url_name']
    ordering_fields = ['id','create_time']
    queryset = OperationRecord.objects.filter(del_flag=False)


class LoginLogsViewSet(ModelViewSet):
    """登录日志"""
    serializer_class = LoginLogSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    permission_classes = [IsAuthenticated]
    pagination_class = OperationRecordsPagination
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    filter_class = LoginLogFilter
    search_fields = ['user__name','ip_address','user_agent']
    ordering_fields = ['id','create_time']
    queryset = LoginLog.objects.all()




class DepartmentsViewSet(ModelViewSet):
    """部门"""
    serializer_class = DepartmentsSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    # permission_classes = [IsAuthenticated]
    pagination_class = PaginationCls
    search_fields = ['name']
    ordering_fields = ['id','name','index']
    queryset = Department.objects.all()


class JobsViewSet(ModelViewSet):
    """职务"""
    serializer_class = JobsSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    # permission_classes = [IsAuthenticated]
    pagination_class = PaginationCls
    search_fields = ['name']
    ordering_fields = ['id','name','index']
    queryset = Job.objects.all()

class DictsViewSet(ModelViewSet):
    """职务"""
    serializer_class = DictsSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    # permission_classes = [IsAuthenticated]
    pagination_class = OptionPaginationCls
    search_fields = ['name']
    ordering_fields = ['id','name',]
    queryset = Dict.objects.all()

    def get_queryset(self):
        qs = super().get_queryset()
        sys_name = self.request.GET.get('sys_name', None)  # 获取前端传来的sys_name参数
        if sys_name:
            qs = qs.filter(id__contains=sys_name) # 过滤出id包含sys_name的Dict对象
        return qs.prefetch_related('dict_item').order_by('dict_item__index')


class RegionsViewSet(ModelViewSet):
    serializer_class = RegionsSerializer
    pagination_class = PaginationCls
    search_fields = ['name']
    ordering_fields = ['id','name','index']
    queryset = Region.objects.all()
    #把数据组装成市、区县的列表格式
    def list(self, request):
        queryset = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(queryset, many=True)
        # print(len(serializer.data))
        # 遍历出每个order item
        quxians =[]
        for item in serializer.data:
            if item['region_level']==2:
                children = []
                for quxian in serializer.data:
                    if item['id']==quxian['region_parent_id']:
                        quxian['value'] = quxian['id']
                        quxian['label'] = quxian['region_name']
                        quxian.pop('id')
                        quxian.pop('region_name')
                        children.append(quxian)
                    item['children']=children
                item['value']=item['id']
                item['label']=item['region_name']
                item.pop('id')
                item.pop('region_name')
                quxians.append(item)
            # 将order中的'sales_goods_items'中的'clAmount'、'jgAmount'进行求和clAmount_sum、jgAmount_sum
        print(quxians)
        data={
            "results":quxians
        }
        return Response(data=data, status=status.HTTP_200_OK)


class UserViewSet(ModelViewSet):
    """用户"""

    serializer_class = UserSerializer
    # permission_classes = [IsAuthenticated, IsManagerPermission]
    pagination_class = Pagination
    filterset_fields = ['is_active']
    search_fields = ['username', 'name', 'phone', 'email']
    ordering_fields = ['id', 'username', 'name']
    queryset = User.objects.all()

    def perform_destroy(self, instance):
        if instance.is_manager:
            raise ValidationError('无法删除管理员账号')

        try:
            instance.delete()
        except ProtectedError:
            raise ValidationError(f'用户[{instance.username}]已被引用, 无法删除')

    @extend_schema(request=None, responses={200: None})
    @action(detail=True, methods=['post'])
    def reset_password(self, request, *args, **kwargs):
        """重置密码"""

        instance = self.get_object()
        instance.password = make_password(self.user.username)
        instance.save(update_fields=['password'])

        return Response(status=status.HTTP_200_OK)

class UserActionViewSet(FunctionViewSet):
    """用户操作"""
    # 发送短信验证码 18308576111
    # @extend_schema(request=None, responses={200: None})
    @extend_schema(request=SMSRequest, responses={200: GetTokenResponse})
    @action(detail=False, methods=['post'])
    def send_sms(self, request, *args, **kwargs):
        serializer = SMSRequest(data=request.data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data
        phone_num=decode(validated_data['mobile'],'mobile')
        sys_name=validated_data['sys_name']
        if not (user := User.objects.filter(phone=phone_num).first()):
            raise ValidationError('用户不存在')
        data = request.data
        try:
            App_ID_New = APP_ID
            if sys_name == 'Evaluation':
                App_ID_New = APP_ID_Evaluation
            mobile = phone_num
            data = {
                "method": SEND_SMS_METHOD,
                "appid": App_ID_New,
                "masterAcc": mobile,
            }
            resp = send_sms_code(data)
        except Exception as e:
            print(e)
            raise ValidationError("获取验证码失败，请检查手机号码是否正确或是否已经申请了VPN权限！")
        return Response(resp)

    # 短信验证码版
    @extend_schema(request=GetTokenRequest, responses={200: GetTokenResponse})
    @action(detail=False, methods=['post'])
    def get_token(self, request, *args, **kwargs):
        """获取令牌"""
        serializer = SMSGetTokenRequest(data=request.data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data
        mobile = decode(validated_data['mobile'], 'mobile')
        sys_name = validated_data['sys_name']
        if not (user := User.objects.filter(phone=mobile).first()):
            raise ValidationError('用户不存在')

        # try:
        #     App_ID_New = APP_ID
        #     if sys_name == 'Evaluation':
        #         App_ID_New = APP_ID_Evaluation
        #     code = decode(validated_data['code'],'code')
        #     data = {
        #         "method": AUTH_SMS_METHOD,
        #         "appid": App_ID_New,
        #         "masterAcc": mobile,
        #         "smsPwd": code,
        #     }
        #     resp = send_sms_code(data)
        #     result = resp['SSO']['RESULT']
        #     result_msg = resp['SSO']['RESULT_MSG']
        #     if(result=='0'):
        #         raise ValidationError(result_msg)
        # except Exception as e:
        #     raise ValidationError(result_msg)

        if not user.is_active and not user.is_manager:
            raise ValidationError('用户未激活')
        token = RefreshToken()
        # user = request.user
        ip_address = request.META.get('REMOTE_ADDR')
        user_agent = request.META.get('HTTP_USER_AGENT')
        login_log = LoginLog(user=user, ip_address=ip_address, user_agent=user_agent)
        login_log.save()
        token['user_id'] = user.id
        data = {'refresh': str(token), 'access': str(token.access_token)}

        return Response(data=data, status=status.HTTP_200_OK)

    # @extend_schema(request=GetTokenRequest, responses={200: GetTokenResponse})
    # @action(detail=False, methods=['post'])
    # def get_token(self, request, *args, **kwargs):
    #     """获取令牌"""
    #     serializer = GetTokenRequest(data=request.data)
    #     # print(User.objects.filter(username=validated_data['username']).first())
    #     serializer.is_valid(raise_exception=True)
    #     validated_data = serializer.validated_data
    #     if not (user := User.objects.filter(username=validated_data['username']).first()):
    #         raise ValidationError('用户不存在')
    #
    #     if not check_password(validated_data['password'], user.password):
    #         raise AuthenticationFailed('密码错误')
    #
    #     if not user.is_active and not user.is_manager:
    #         raise ValidationError('用户未激活')
    #
    #     token = RefreshToken()
    #     token['user_id'] = user.id
    #     data = {'refresh': str(token), 'access': str(token.access_token)}
    #
    #     return Response(data=data, status=status.HTTP_200_OK)

    @extend_schema(request=RefreshTokenRequest, responses={200: RefreshTokenResponse})
    @action(detail=False, methods=['post'])
    def refresh_token(self, request, *args, **kwargs):
        """刷新令牌"""

        serializer = RefreshTokenRequest(data=request.data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data

        try:
            token = RefreshToken(validated_data['refresh'])
        except TokenError:
            raise NotAuthenticated('令牌失效')

        data = {'access': str(token.access_token)}
        return Response(data=data, status=status.HTTP_200_OK)

    @extend_schema(responses={200: UserInfoResponse})
    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
    def info(self, request, *args, **kwargs):
        """用户信息"""

        serializer = UserInfoResponse(instance=self.user)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    @extend_schema(request=SetPasswordRequest, responses={204: None})
    @action(detail=False, methods=['post'], permission_classes=[IsAuthenticated])
    def set_password(self, request, *args, **kwargs):
        """设置密码"""

        serializer = SetPasswordRequest(data=request.data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data

        if not check_password(validated_data['old_password'], self.user.password):
            raise AuthenticationFailed('密码错误')

        self.user.password = make_password(validated_data['new_password'])
        self.user.save(update_fields=['password'])

        return Response(status=status.HTTP_200_OK)


__all__ = [
    'PermissionGroupViewSet',
    'SystemConfigViewSet',
    'CompaniesViewSet',
    'TodolistsViewSet',
    'DepartmentsViewSet',
    'JobsViewSet',
    'DictsViewSet',
    'RoleViewSet', 'UserViewSet', 'UserActionViewSet',

]
